package org.alis.rpc.client;

import org.alis.rpc.common.annotation.RpcAutowired;
import org.alis.rpc.discovery.ServiceDiscovery;
import org.alis.rpc.manager.ConnectManager;
import org.alis.rpc.proxy.ObjectProxy;
import org.alis.rpc.proxy.RpcService;
import org.alis.rpc.proxy.SerializableFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;

import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

/**
 * AlisApcClient desc:
 *
 * @author luochuan
 * @date 2020/9/30
 */
public class AlisRpcClient implements ApplicationContextAware, DisposableBean {
    private static final Logger logger = LoggerFactory.getLogger(AlisRpcClient.class);


    private ServiceDiscovery serviceDiscovery;

    public AlisRpcClient(String address){

    }

    public static <V,P> RpcService<V,P,SerializableFunction> createAsyncService(Class<?> interfaceClass, String version) {
         return new ObjectProxy<>(version, interfaceClass);
    }

    @SuppressWarnings("unchecked")
    public static <T, P> T createService(Class<T> interfaceClass, String version) {
        return (T) Proxy.newProxyInstance(
                interfaceClass.getClassLoader(),
                new Class<?>[]{interfaceClass},
                new ObjectProxy<T, P>(version,interfaceClass)
        );
    }

    @Override
    public void destroy() throws Exception {
        stop();
    }


    @Override
    public void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException {
        Assert.notNull(applicationContext,"");
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            Object bean = applicationContext.getBean(beanName);
            Field[] fields = bean.getClass().getDeclaredFields();
            try {
                for (Field field : fields) {
                    RpcAutowired rpcAutowired = field.getAnnotation(RpcAutowired.class);
                    if (rpcAutowired != null) {
                        String version = rpcAutowired.version();
                        field.setAccessible(true);
                        field.set(bean, createService(field.getType(), version));
                    }
                }
            } catch (IllegalAccessException e) {
                logger.error(e.toString());
            }
        }
    }



    public void stop() {
        serviceDiscovery.stop();
        ConnectManager.getInstance().stop();
    }
}
